const { Sequelize, Model, DataTypes } = require('sequelize');


  
class DatabaseService{
    constructor(dbroot){
        this.sequelize = new Sequelize({
            dialect: 'sqlite',
            storage: dbroot + '/database.sqlite'
          }) // Example for sqlite
    }
    async defineModels(){
        this.Project = this.sequelize.define('Project', {
            // Model attributes are defined here
            projectId:{
                type: DataTypes.INTEGER,
                autoIncrement:true,
                primaryKey:true
        
            },
            projectName: {
                type: DataTypes.STRING,
                allowNull: false
            },
            description: {
                type: DataTypes.STRING,
                allowNull: false
            },
            currentVersionId:{
                type: DataTypes.INTEGER,
                defaultValue: 0
            },
            projectType:{
                type:DataTypes.INTEGER,
                defaultValue:1
            }
        });

        this.Version = this.sequelize.define('Version', {
            versionId:{
                type: DataTypes.INTEGER,
                autoIncrement:true,
                primaryKey:true
            },
            projectId:{
                type:DataTypes.INTEGER,
                allowNull:false
            },
            filePath: {
                type: DataTypes.STRING,
                allowNull: false
            },
            webPath: {
                type: DataTypes.STRING,
                allowNull: false
            },
            changeList: {
                type: DataTypes.TEXT,
                allowNull: false
            },
            uploadDateTime:{
                type: DataTypes.DATE
            }
        });
        await this.sequelize.sync({alter:true});
        // Create one to many association
        this.Project.hasOne(this.Version,{as:'currentVersion',sourceKey:'currentVersionId',foreignKey:'versionId'});
        this.Project.hasMany(this.Version,{as:'versions',sourceKey:'projectId',foreignKey:'projectId'});
    }
    async connect(){
        if(this.connected){
            return true;
        }
        try {
            await this.sequelize.authenticate();
            await this.defineModels();

            console.log('Connection has been established successfully.');
            this.connected = true;
            return true;
        } catch (error) {
            console.error('Unable to connect to the database:', error);
            this.connected = false;
            return false;
        }
    }
    //Add new Project
    async addProject(project){
        if(this.connected){
            return this.Project.create(project,{isNewRecord:true});
        }
        return null;
    }
    // updateProject 
    async updateProject(project){
        if(this.connected){
            return this.Project.update(project,{ where:{projectId:project.projectId}});
        }
        return null;
    }
    //List All project
    async listProjects(){
        if(this.connected){
            return this.Project.findAll({include:[{model:this.Version,as:'currentVersion'}]});
        }else{
            return [];
        }
    }
    async findProjectById(projectId){
        if(this.connected){
            return this.Project.findOne({where:[{'projectId':projectId}],include:[{model:this.Version,as:'versions'}]});
        }else{
            return [];
        }
    }
    //Add new Version
    async addVersion(version){
        if(this.connected){
            console.log("add version parameter:",version);
            return this.Version.create(version,{isNewRecord:true});
        }
        return null;
    }
    async findVersionById(id){
        if(this.connected){
            return this.Version.findOne({versionId:id});
        }
        return null;
    }
}
let DaoInstance = null;
const getDao=(config)=>{
    
    const {dbroot} = config?config:{dbroot:process.env.DB_ROOT};

    if(DaoInstance == null)
        DaoInstance =  new DatabaseService(dbroot);
    return DaoInstance;
}
module.exports = getDao;